﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

using Robert.TwitBy.Properties;
using Robert.TwitBy.Models;
using Robert.TwitBy.ViewModels;

using TweetSharp.Twitter.Model;
using TweetSharp.Twitter.Fluent;
using TweetSharp.Twitter.Extensions;



namespace Robert.TwitBy.Callers
{
    public abstract class TwitterCaller
    {
        public TwitterCaller(TwitterViewModel model)
        {
            _model = model;
        }

        private string _consumerKey = Settings.Default.ConsumerKey;
        private string _cosumerSecret = Settings.Default.ConsumerSecret;
        private string _accessKey { get { return Settings.Default.AccessToken; } }
        private string _accessSecret { get { return Settings.Default.AccessTokenSecret; } }
        private int _tweetToGet { get { return Settings.Default.TweetsToGet; } }
        private TwitterViewModel _model;
        private int Pages;
        private int TweetsToGet;

        public void HomeTweets()
        {
            _model.IsRefreshing = true;

            var twitter = CreateRequest();
            
            GettingTweets();

            if ((bool)_model.IsHomeCheck)
                twitter.Statuses().OnHomeTimeline().Take(200).CallbackTo(GotResponse).BeginRequest();
            else
                if (_tweetToGet <= 200)
                    twitter.Statuses().OnHomeTimeline().Take(200).CallbackTo(GotResponse).BeginRequest();
                else
                {
                    Pages = (int)Math.Ceiling(_tweetToGet / 200.0);
                    TweetsToGet = (int)Math.Ceiling(_tweetToGet / (double)Pages);

                    for (int i = 1; i <= Pages; i++)
                        twitter.Statuses().OnHomeTimeline().Take(TweetsToGet).Skip(i).CallbackTo(GotResponse).BeginRequest();
                }
        }

        public void YourTweets()
        {
            _model.IsRefreshing = true;

            var twitter = CreateRequest();

            GettingTweets();

            if ((bool)_model.IsHomeCheck)
                twitter.Statuses().OnUserTimeline().For(Settings.Default.UserId).Take(200).CallbackTo(GotResponse).BeginRequest();
            else
                if (_tweetToGet <= 200)
                    twitter.Statuses().OnUserTimeline().For(Settings.Default.UserId).Take(_tweetToGet).CallbackTo(GotResponse).BeginRequest();
                else
                {
                    Pages = (int)Math.Ceiling(_tweetToGet / 200.0);
                    TweetsToGet = (int)Math.Ceiling(_tweetToGet / (double)Pages);

                    for (int i = 1; i <= Pages; i++)
                        twitter.Statuses().OnUserTimeline().For(Settings.Default.UserId).Take(TweetsToGet).Skip(i).CallbackTo(GotResponse).BeginRequest();
                }
        }

        public void MentionTweets()
        {
            _model.IsRefreshing = true;

            var twitter = CreateRequest();

            GettingTweets();

            if ((bool)_model.IsHomeCheck)
                twitter.Statuses().Mentions().Take(200).CallbackTo(GotResponse).BeginRequest();
            else
                if (_tweetToGet <= 200)
                    twitter.Statuses().Mentions().Take(_tweetToGet).CallbackTo(GotResponse).BeginRequest();
                else
                {
                    Pages = (int)Math.Ceiling(_tweetToGet / 200.0);
                    TweetsToGet = (int)Math.Ceiling(_tweetToGet / (double)Pages);

                    for (int i = 1; i <= Pages; i++)
                        twitter.Statuses().Mentions().Take(TweetsToGet).Skip(i).CallbackTo(GotResponse).BeginRequest();
                }
        }

        public void DirectTweets()
        {
            _model.IsRefreshing = true;

            var twitter = CreateRequest();

            GettingTweets();

            if ((bool)_model.IsHomeCheck)
                twitter.DirectMessages().Received().Take(200).CallbackTo(GotResponse).BeginRequest();
            else
                if (_tweetToGet <= 200)
                    twitter.DirectMessages().Received().Take(_tweetToGet).CallbackTo(GotResponse).BeginRequest();
                else
                {
                    Pages = (int)Math.Ceiling(_tweetToGet / 200.0);
                    TweetsToGet = (int)Math.Ceiling(_tweetToGet / (double)Pages);

                    for (int i = 1; i <= Pages; i++)
                        twitter.DirectMessages().Received().Take(TweetsToGet).Skip(i).CallbackTo(GotResponse).BeginRequest();
                }
        }

        private void GotResponse(object sender, TwitterResult result, object userState)
        {
            if (result.IsTwitterError)
                _model.Dispatcher.BeginInvoke(new Action(() => IsTwitterError(result)));
            else
                if (result.IsFailWhale || result.TimedOut)
                    _model.Dispatcher.BeginInvoke(new Action(() => IsTwitterDown(result)));
                else
                    OnSuccesfulResponse(result);
        }

        protected abstract void IsTwitterError(TwitterResult result);
        protected abstract void IsTwitterDown(TwitterResult result);
        protected abstract void OnSuccesfulResponse(TwitterResult result);
        protected abstract void GettingTweets();
        protected abstract void GotTweets();

        private IFluentTwitter CreateRequest()
        {
            return FluentTwitter.CreateRequest()
                .AuthenticateWith(_consumerKey, _cosumerSecret, _accessKey, _accessSecret);
        }
    }
}
